<?php
namespace app\hooks;

use app\api\model\ModeOrders;
use app\api\model\User;

class UserHook
{


    public static function run($user_id, $check_parents = false)
    {
        //设置延迟
        set_time_limit(0);
        //配置内润
        ini_set('memory_limit', '5124M');

        if ($user_info = User::findOrEmpty($user_id)->toArray()) {

            $data = ['update_time' => date('Y-m-d H:i:s')];

            if (!$user_info['parent_ids'] || $check_parents) {

                $user_info['parent_ids'] = $parent_ids = self::getParents($user_id);

                $data['parent_ids'] = $parent_ids ? ('|'.implode('|', $parent_ids).'|') : '';

            }

            $mode_one_infos = self::computeModeOne($user_info);

            $mode_three_infos = self::computeModeThree($user_info);

            User::where('id', $user_info['id'])->update(array_merge($data, $mode_one_infos, $mode_three_infos, [
                'direct_count' => User::where('pid', $user_info['id'])->count(),
                'green_points' => ModeOrders::where('user_id', $user_id)->where('is_delete', 0)->whereIn('type', [1, 2])->where('status', 'payed')->whereNotNull('pay_time')->where('remain_earnings', '>', 0)->sum('remain_earnings'),
                'invest_balance' => ModeOrders::where('user_id', $user_id)->where('is_delete', 0)->whereIn('type', [4])->where('status', 'payed')->whereNotNull('pay_time')->where('remain_earnings', '>', 0)->sum('remain_earnings')
            ]));

            if ((int)$user_info['pid'] > 0) {

                return self::run($user_info['pid']);

            }

        }

        return true;
    }

    /**
     * 转移团队
     * @Author Abnermouke <abnermouke@outlook.com | yunnitec@outlook.com>
     * @Company Chongqing Yunni Network Technology Co., Ltd.
     * @Time 2024-04-19 15:21:45
     * @param $user_id
     * @param $move_to_pid
     * @return true
     */
    public static function move($user_id, $move_to_pid)
    {
        //设置延迟
        set_time_limit(0);
        //配置内润
        ini_set('memory_limit', '5124M');
        //查询用户信息
        $user_info = User::where('id', $user_id)->findOrEmpty()->toArray();
        //判断父级是否改变
        if ((int)$user_info['pid'] !== $move_to_pid) {
            //更改用户邀请人ID
            User::where('id', $user_id)->update(['pid' => $move_to_pid, 'direct_count' => 0, 'parent_ids' => '','update_time' => date('Y-m-d H:i:s')]);
            //设置所有人下级邀请数量
            User::whereLike('parent_ids', '%|.'.$user_id.'.|%')->update(['direct_count' => 0, 'parent_ids' => '', 'update_time' => date('Y-m-d H:i:s')]);
            //设置邀请人邀请数量
            User::where('id', (int)$user_info['pid'])->update(['direct_count' => 0, 'parent_ids' => '', 'update_time' => date('Y-m-d H:i:s')]);
            //重跑结构
            foreach (User::where('direct_count', 0)->order('update_time', 'desc')->order('id', 'desc')->column('id') as $user_id) {

                //重跑
                UserHook::run($user_id, true);
            }
        }
        //返回成功
        return true;
    }

    private static function computeModeThree($user_info)
    {

        $mode_three_spending = (int)$user_info['mode_three_spending'];
        $mode_three_performance = $user_info['mode_three_performance'] = $user_info['mode_three_min_performance'] = 0;

        if ($direct_users = User::where('pid', $user_info['id'])->field('id, mode_three_total')->order('mode_three_total', 'desc')->select()) {

            $direct_users = $direct_users->toArray();

            $mode_three_performance = $user_info['mode_three_performance'] = (int)array_sum(array_column($direct_users, 'mode_three_total'));

            unset($direct_users[0]);

            if ($direct_users) {

                $user_info['mode_three_min_performance'] = (int)array_sum(array_column($direct_users, 'mode_three_total'));

            }

        }

        $mode_three_total = $user_info['mode_three_total'] = $mode_three_spending + $mode_three_performance;

        $mode_three_levels = self::computeModeThreeLevel($user_info);

        return array_merge(compact('mode_three_spending', 'mode_three_performance', 'mode_three_total'), $mode_three_levels);
    }

    private static function computeModeThreeLevel($user_info)
    {
        $level_conditions = [
            1 => ['performance' => 0,'min_performance' => 1000000, 'sub_level_id' => 0, 'sub_level_count' => 0],
            2 => ['performance' => 0,'min_performance' => 5000000, 'sub_level_id' => 0, 'sub_level_count' => 0],
            3 => ['performance' => 30000000,'min_performance' => 0, 'sub_level_id' => 2, 'sub_level_count' => 2],
            4 => ['performance' => 100000000,'min_performance' => 0, 'sub_level_id' => 3, 'sub_level_count' => 2],
            5 => ['performance' => 300000000,'min_performance' => 0, 'sub_level_id' => 4, 'sub_level_count' => 2],
            6 => ['performance' => 1000000000,'min_performance' => 0, 'sub_level_id' => 5, 'sub_level_count' => 2],
        ];

        $mode_three_performance = (int)$user_info['mode_three_performance'];
        $mode_three_min_performance = (int)$user_info['mode_three_min_performance'];

        $mode_three_real_level_id = 0;

        foreach ($level_conditions as $level_id => $condition) {

            if ($condition['performance'] > 0 && $mode_three_performance < $condition['performance']) {
                break;
            }

            if ($condition['min_performance'] > 0 && $mode_three_min_performance < $condition['min_performance']) {
                break;
            }

            if ($condition['sub_level_id'] > 0 && $condition['sub_level_count'] > 0) {

                if (!$direct_users = User::where('pid', $user_info['id'])->field('id, mode_three_real_level_id')->select()) {

                    break;

                }

                $direct_users = $direct_users->toArray();

                $current_sub_level_count = 0;

                foreach ($direct_users as $direct_user) {

                    if ((int)$direct_user['mode_three_real_level_id'] >= (int)$condition['sub_level_id']) {

                        $current_sub_level_count += 1;

                        continue;

                    }

                    if (User::whereLike('parent_ids',  '%|'.$direct_user['id'].'|%')->where('mode_three_real_level_id', '>=', $condition['sub_level_id'])->count() > 0) {

                        $current_sub_level_count += 1;

                    }

                }

                if ($current_sub_level_count < $condition['sub_level_count']) {

                    continue;

                }

            }

            $mode_three_real_level_id = $level_id;

        }

        $mode_three_level_id = max($mode_three_real_level_id, (int)$user_info['mode_three_level_id']);


        return compact('mode_three_real_level_id', 'mode_three_level_id');

    }

    private static function computeModeOne($user_info)
    {

        $mode_one_spending = (int)$user_info['mode_one_spending'];
        $mode_one_performance = $user_info['mode_one_performance'] = (int)User::where('pid', $user_info['id'])->sum('mode_one_total');
        $mode_one_total = $user_info['mode_one_total'] = $mode_one_spending + $mode_one_performance;

        $mode_one_levels = self::computeModeOneLevel($user_info);

        return array_merge(compact('mode_one_spending', 'mode_one_performance', 'mode_one_total'), $mode_one_levels);
    }

    private static function computeModeOneLevel($user_info)
    {
        $level_conditions = [
            1 => ['performance' => 10000000, 'sub_level_id' => 0, 'sub_level_count' => 0],
            2 => ['performance' => 50000000, 'sub_level_id' => 1, 'sub_level_count' => 2],
            3 => ['performance' => 300000000, 'sub_level_id' => 2, 'sub_level_count' => 2],
            4 => ['performance' => 1000000000, 'sub_level_id' => 3, 'sub_level_count' => 2],
        ];

        $mode_one_performance = (int)$user_info['mode_one_performance'];

        $mode_one_real_level_id = 0;

        foreach ($level_conditions as $level_id => $condition) {

            if ($mode_one_performance < $condition['performance']) {
                break;
            }

            if ($condition['sub_level_id'] > 0 && $condition['sub_level_count'] > 0) {

                if (!$direct_users = User::where('pid', $user_info['id'])->field('id, mode_one_real_level_id')->select()) {

                    break;

                }

                $direct_users = $direct_users->toArray();

                $current_sub_level_count = 0;

                foreach ($direct_users as $direct_user) {

                   if ((int)$direct_user['mode_one_real_level_id'] >= (int)$condition['sub_level_id']) {

                       $current_sub_level_count += 1;

                       continue;

                   }

                   if (User::whereLike('parent_ids',  '%|'.$direct_user['id'].'|%')->where('mode_one_real_level_id', '>=', $condition['sub_level_id'])->count() > 0) {

                       $current_sub_level_count += 1;

                   }

                }

                if ($current_sub_level_count < $condition['sub_level_count']) {

                    continue;

                }

            }

            $mode_one_real_level_id = $level_id;

        }

        $mode_one_level_id = max($mode_one_real_level_id, (int)$user_info['mode_one_level_id']);


        return compact('mode_one_real_level_id', 'mode_one_level_id');
    }

    private static function getParents($user_id, $parent_ids = [])
    {
        if ($pid = (int)User::where('id', $user_id)->value('pid')) {

            $parent_ids[] = $pid;

            return self::getParents($pid, $parent_ids);

        }

        return $parent_ids;
    }


}